<?php
/**
 * Created by PhpStorm.
 * User: qgkjtech
 * Date: 2017/10/13
 * Time: 下午3:29
 * 用于判断牛牛的算法逻辑
 */
require_once('NiuniuType.php');
require_once('NiuNiuCard.php');
class NiuniuLogic{

    /**
     * 辅助函数，用于排序
     * @param $cards 卡牌的引用
     */

    private function sortPlayerCards(&$cards){
        for($i = 0; $i < 5; $i++){
            for($j = 0; $j < 4 - $i; $j++){
                if($cards[$j]->num > $cards[$j + 1]->num ||
                    ($cards[$j]->num == $cards[$j+1]->num && $cards[$j]->type < $cards[$j+1]->type)){
                    $t = $cards[$j];
                    $cards[$j] = $cards[$j+1];
                    $cards[$j+1] = $t;
                }
            }
        }
    }


    /**
     * @param $playerCards 玩家的手牌，这里假设的是以{玩家ID,Cards（array）}的方式传过来的数据
     * @param $typeSelected  允许的可选牌型的数组，用于是否开启该牌型，包含数据为
     *          canShunDou: 能否顺斗; canKanDou: 能否坎斗
     *          canTongHuaShun: 能否同花顺
     *          canZhaDanNiu: 能否炸弹牛
     *          canWuXiaoNiu: 能否五小牛
     *          canWuHuaNiu:  能否五花牛
     *          canSiHuaNiu:  能否四花牛
     *          canHuLuNiu:   能否葫芦牛
     *          canTongHuaNiu: 能否同花牛
     *          canShunZiNiu:  能否顺子牛
     * @return $resultArray 某一个玩家的结果数组，存放结果
     *          'playerID' ： 对应的玩家
     *          'level': 牌的级别，按照同花顺 > 五小牛 > 五花牛 > 四花牛 > 炸弹牛 > 葫芦牛 > 同花
     *                                     > 顺子 > 牛牛 > 牛9-牛5 > 牛4-牛1 > 无牛进行排列
     *                         注意：坎斗、顺斗以及普通牛是同一级别，都看点数
     *          'levelResult': 牌的级别对应的最大牌，用于同级别的判断
     *
     */

    public function getNiuniuResult($playerCards, $typeSelected){
        $resultArray = array();//array('playerID'=>'', 'level'=>0, 'levelResult'=>'');
        for($i = 0; $i < count($playerCards); $i++){
            //初始化一个基本结果，然后和所有数据判断
            $resultArray[$i]['playerID'] = $playerCards[$i]['playerID'];
            $resultArray[$i]['level'] = -1;
            $resultArray[$i]['levelResult'] = '';

            //保存一个临时牌组，并按从小到大排序
            $cards = $playerCards[$i]['cards'];
            $this->sortPlayerCards($cards);


            //获取普通牛数据
            $r = $this->getNiuniuCount($cards);
            $this->processResult($resultArray[$i], $r);

            if($typeSelected['canShunDou']){
                //获取顺斗的数据
                $r = $this->getShunDouPoint($cards);
                $this->processResult($resultArray[$i], $r);
            }

            if($typeSelected['canCanDou']){
                //获取坎斗的数据
                $r = $this->getKanDouPoint($cards);
                $this->processResult($resultArray[$i], $r);
            }

            if($typeSelected['canShunZiNiu']){
                //获取顺子牛数据
                $r = $this->isShunZiNiu($cards);
                $this->processResult($resultArray[$i], $r);
            }

            if($typeSelected['canTongHuaNiu']){
                //获取同花牛
                $r = $this->isTonghuaNiu($cards);
                $this->processResult($resultArray[$i], $r);
            }

            if($typeSelected['canHuLuNiu']){
                //获取葫芦牛
                $r = $this->huluNiu($cards);
                $this->processResult($resultArray[$i], $r);
            }

            if($typeSelected['canZhaDanNiu']){
                //获取炸弹牛
                $r = $this->isBoomNiu($cards);
                $this->processResult($resultArray[$i], $r);
            }

            if($typeSelected['canSiHuaNiu']){
                //获取四花牛
                $r = $this->isSiHuaNiu($cards);
                $this->processResult($resultArray[$i], $r);
            }

            if($typeSelected['canWuHuaNiu']){
                //获取五花牛
                $r = $this->isWuHuaNiu($cards);
                $this->processResult($resultArray[$i], $r);
            }

            if($typeSelected['canWuXiaoNiu']){
                //获取五小牛
                $r = $this->isWuXiaoNiu($cards);
                $this->processResult($resultArray[$i], $r);
            }

            if($typeSelected['canTongHuaShun']){
                //获取同花顺
                $r = $this->isTongHuaShun($cards);
                $this->processResult($resultArray[$i], $r);
            }

        }
        return $resultArray;
    }

    private function processResult(&$playerResult, $newResult){
        if($playerResult['level'] < $newResult['level']){
            $playerResult['level'] = $newResult['level'];
            $playerResult['levelResult'] = $newResult['maxCard'];
        }
    }

    /**
     * 判断牛牛点数
     * @param $playerCards 玩家的手牌，这里假设的是以玩家ID=》Cards（array）的方式传过来的数据
     * @return $array:[level:牌力，maxCard: 最大牌]
     */
    private function getNiuniuCount($playerCard){
        $result = array();
        //总点数
        $cardsTotalPoint = 0;
        //计算总点数
        for($i = 0; $i < count($playerCard); $i++){
            $cardsTotalPoint += $playerCard[$i]->count;
        }
        //计算余数
        $lave = $cardsTotalPoint % 10;
        for($i = 0; $i < count($playerCard) - 1; $i++){
            for($j = $i + 1; $j < count($playerCard); $j++){
                if(($playerCard[$i]->count + $playerCard[$j]->count) % 10 == $lave){
                    $result['level'] = $this->_getCount($lave);
                    $result['maxCard'] = $playerCard[$j];
                    return $result;
                }
            }
        }
        $result['level'] = WUNIU;
        $result['maxCard'] = $playerCard[4];
        return $result;

    }

    /*
     * 辅助函数，用于处理牛1-牛9的细分结果处理
     * @param $lave: getNiuniuCount的余数结果
     */
    private function _getCount($lave)
    {
        switch ($lave) {
            case 0:
                return NIUNIU;
            case 1:
                return NIUNIU1;
            case 2:
                return NIUNIU2;
            case 3:
                return NIUNIU3;
            case 4:
                return NIUNIU4;
            case 5:
                return NIUNIU5;
            case 6:
                return NIUNIU6;
            case 7:
                return NIUNIU7;
            case 8:
                return NIUNIU8;
            case 9:
                return NIUNIU9;

            default:
                return -1;
        }
    }


    /**
     * 判断是否为五花牛的函数
     * @param $playerCard 某一个玩家的手牌
     * @return $array:[level: 牌力，maxCard: 最大牌]
     */
    private function isWuHuaNiu($playerCard){
        $result = array('level'=>-1, 'maxCard'=>'');
        for($i = 0; $i < count($playerCard); $i++){
            if($playerCard[$i]->num <= 10){
                return $result;
            }
        }
        $result['level'] = WUHUANIU;
        $result['maxCard'] = $playerCard[4];
        return $result;
    }

    /**
     * 判断是否为同花牛的函数
     * @param $playerCard 某一个玩家的手牌
     * @return $array:[level:牌力，maxCard: 最大牌]
     */
    private function isTonghuaNiu($playerCard){
        $result = array('level'=>-1, 'maxCard'=>'');
        $type = $playerCard[0]->type;
        $isTonghua = true;
        for($i = 1; $i < count($playerCard); $i++){
            if($type != $playerCard[$i]->type){
                $isTonghua = false;
                break;
            }
        }

        if($isTonghua){
            $result['level'] = TONGHUANIU;
            $result['maxCard'] = $playerCard[4];
        }

        return $result;
    }


    /**
     * 判断是否为同花顺牛的函数
     * @param $playerCard
     * @return array:[level:牌力, maxCard: 同花顺的最大牌]
     */
    private function isTongHuaShun($playerCard){
        $result = array('level'=>-1, 'maxCard'=>'');
        $r1 = $this->isTonghuaNiu($playerCard);
        $r2 = $this->isShunZiNiu($playerCard);
        if($r1['level'] == TONGHUANIU && $r2['level'] = SHUNZINIU){
            $result['level'] = TONGHUASHUN;
            $result['maxCard'] = $playerCard[4];
        }

        return $result;
    }


    /**
     * 判断是否为炸弹牛的函数
     * @param $playerCard 某一个玩家的手牌
     * @return $array:[level:牌力，maxCard: 炸弹牌]
     */
    private function isBoomNiu($playerCard){
        $result = array('level'=>-1, 'maxCard'=>'');
        //假设牌已经按照从小到大排序
        //aaaa*
        if($playerCard[0]->num == $playerCard[3]->num){
            $result['level'] = ZHADANNIU;
            $result['maxCard'] = $playerCard[0];
        }
        //*aaaa
        else if($playerCard[1]->num == $playerCard[4]->num){
            $result['level'] = ZHADANNIU;
            $result['maxCard'] = $playerCard[1];
        }
        else{
            $result['level'] = -1;
            $result['maxCard'] = '';
        }
        return $result;
    }

    /**
     * 判断是否为五小牛的函数
     * @param $playerCard 某一个玩家的手牌
     * @return $array:[level:是否为五小牛, maxCard:最大的卡牌]
     */
    private function isWuXiaoNiu($playerCard){
        $result = array('level'=>-1, 'maxCard'=>'');
        $totalCount = 0;
        for($i = 0; $i < count($playerCard); $i++){
            if($playerCard[$i]->num > 5){
                return $result;
            }
            else{
                $totalCount += $playerCard[$i]->count;
            }
        }
        if($totalCount < 10 && $totalCount > 0){
            $result['level'] = WUXIAONIU;
            $result['maxCard'] = $playerCard[4];
        }

        return $result;
    }

    /**
     * 判断是否为葫芦牌型的函数
     * @param $playerCard 某一个玩家的手牌
     * @return $array: [level:是否为葫芦牛, maxCard:葫芦的点数最大牌]
     */
    private function huluNiu($playerCard){
        $result = array('level'=>-1, 'maxCard'=>0);
        //aaabb
        if($playerCard[0]->num == $playerCard[2]->num){
            if($playerCard[3]->num == $playerCard[4]->num){
                $result['level'] = HULUNIU;
                $result['maxCard'] = $playerCard[0];
            }
        }
        //aabbb
        if($playerCard[2]->num == $playerCard[4]->num){
            if($playerCard[0]->num == $playerCard[1]->num){
                $result['isHuluNiu'] = 1;
                $result['maxPoint'] = $playerCard[2]->num;
            }
        }
        return $result;
    }

    /**
     * 判断是否为四花型的函数
     * @param $playerCard 某一个玩家的手牌
     * @return $array:[level:是否为四花牛, maxCard:四花的最大牌]
     */
    private function isSiHuaNiu($playerCard){
        $result = array('level'=>-1, 'maxCard'=>'');
        $temp = true;
        for($i = 0; $i < count($playerCard); $i++){
            if($playerCard[$i]->num < 10){
                $temp = false;
                break;
            }
        }
        if($playerCard[0]->num == 10 && $temp){
            $result['level'] = SIHUANIU;
            $result['maxCard'] = $playerCard[4];
        }

        return $result;
    }

    /**
     * 判断是否为顺子牛的函数
     * @param $playerCard 某一个玩家的手牌
     * @return $array:[level:是否为顺子牛, maxCard:顺子牛的最大牌]
     */
    private function isShunZiNiu($playerCard){
        $result = array('level'=>-1, 'maxCard'=>'');
        //abcde, a + 4 = e
        if($playerCard[0]->num + 4 == $playerCard[4]->num){
            $result['level'] = SHUNZINIU;
            $result['maxCard'] = $playerCard[4];
        }


        return $result;
    }

    /**
     * 获取是否为坎斗的函数
     * @param $playerCard 某一个玩家的手牌
     * @return $result:[level:坎斗形成的点数, maxCard: 坎斗中的最大牌]
     */
    private function getKanDouPoint($playerCard){
        $result = array('level'=>-1, 'maxCard'=>'');
        //aaa**
        if($playerCard[0]->num == $playerCard[2]->num){
            $count = $playerCard[3]->point + $playerCard[4]->point;
            $result['maxCard'] = $playerCard[4];
        }
        //*aaa*
        else if($playerCard[1]->num == $playerCard[3]->num){
            $count = $playerCard[0]->point + $playerCard[4]->point;
            $result['maxCard'] = $playerCard[4];
        }
        //**aaa
        else if($playerCard[2]->num == $playerCard[4]->num){
            $count = $playerCard[0]->point + $playerCard[1]->point;
            $result['maxCard'] = $playerCard[1];
        }
        else{
            $count = -1;
        }
        $count = $count % 10;

        $result['level'] = $this->_getCount($count);
        return $result;
    }

    /**
     * 获取是否为顺斗的函数
     * @param $playerCard 某一个玩家的手牌
     * @return $result:[level:顺斗形成的点数, maxCard: 顺斗中的最大牌]
     */
    private function getShunDouPoint($playerCard){
        $result = array('level'=>-1, 'maxCard'=>'');

        //枚举所有情况产生点数的数组
        $tempResult = array();
        //第一种情况abc**
        if( ($playerCard[0]->num+1 == $playerCard[1]->num) && ($playerCard[1]->num == $playerCard[2]->num - 1)){
            array_push($tempResult, array('level'=>$playerCard[3]->count + $playerCard[4]->count, 'maxCard'=>$playerCard[4]));
        }
        //第二种情况*abc*
        if (($playerCard[1]->num+1 == $playerCard[2]->num) && ($playerCard[2]->num == $playerCard[3]->num - 1)){
            array_push($tempResult, array('level'=>$playerCard[0]->count + $playerCard[4]->count, 'maxCard'=>$playerCard[4]));
        }

        //第三种情况**abc
        if (($playerCard[2]->num+1 == $playerCard[3]->num) && ($playerCard[3]->num == $playerCard[4]->num - 1)){
            array_push($tempResult, array('level'=>$playerCard[0]->count + $playerCard[1]->count, 'maxCard'=>$playerCard[4]));
        }

        //第四种情况abbc*
        if ($playerCard[0]->num+2 == $playerCard[3]->num){
            array_push($tempResult, array('level'=>$playerCard[0]->count + $playerCard[1]->count, 'maxCard'=>$playerCard[4]));
        }

        //第五种情况*bccd;
        if($playerCard[1]->num+2 == $playerCard[4]->num){
            array_push($tempResult, array('level'=>$playerCard[0]->count + $playerCard[2]->count, 'maxCard'=>$playerCard[3]));
        }

        //第六种情况aabbc;
        if(($playerCard[0]->num+1 == $playerCard[2]->num+1) && ($playerCard[2]->num+1 == $playerCard[4]->num)){
            array_push($tempResult, array('level'=>$playerCard[0]->count + $playerCard[2]->count, 'maxCard'=>$playerCard[3]));
        }

        //第七种情况abbcc
        if(($playerCard[0]->num+1 == $playerCard[2]->num) && ($playerCard[2]->num+1 == $playerCard[4]->num)){
            array_push($tempResult, array('level'=>$playerCard[1]->count + $playerCard[3]->count, 'maxCard'=>$playerCard[4]));
        }

        //第8种情况abbbc
        if($playerCard[0]->num+2 == $playerCard[4]->num){
            array_push($tempResult, array('level'=>$playerCard[1]->count * 2, 'maxCard'=>$playerCard[3]));
        }

        //有可能没有结果，直接返回
        if(count($tempResult) == 0){
            return $result;
        }

        //获取最大的可能性结果返回
        $level = $tempResult[0]['level'];
        $index = 0;
        for($i = 1; $i < count($tempResult); $i++){
            if($tempResult[$i]['level'] > $level){
                $index = $i;
            }
        }
        echo $tempResult[$index]['level'];
        $result['level'] = $this->_getCount($tempResult[$index]['level'] % 10 );
        $result['maxCard'] = $tempResult[$index]['maxCard'];

        return $result;

    }


}






?>